import re
import os
import pickle
import urllib.request
import datetime

RESULT_STR = r'<tr><td>(?P<place>.*?)</td><td><a href="http://olympiads\.ru/cgi-bin/users\?contest_id=25&user_id=(?P<userid>\d+?)&locale_id=1">(?P<login>.*?)</a></td><td width="120" class="st_extra"><b>(?P<region>.*?)</b>: (?P<city>.+?), (?P<school>.+?), (?P<grade>.+?)</td>(?P<results>.*?)<td>\d+?</td><td>\d+?</td></tr>'

USER_STR = r'''<table>
<tr><td>NN:</td><td>.*?</td></tr>
<tr><td>Имя:</td><td>(?P<name>.*?)</td></tr>
<tr><td>Отчество:</td><td>(?P<middlename>.*?)</td></tr>
<tr><td>Фамилия:</td><td>(?P<surname>.*?)</td></tr>
<tr><td>Статус:</td><td>(?P<status>.*?)</td></tr>
<tr><td>Уровень \(класс, курс\):</td><td>(?P<grade>.*?)</td></tr>
</table>'''

page_url = lambda n: r'http://olympiads.ru/zaoch/2012-13/standings/standings%s.shtml' % (str(n) if n != 1 else '')
user_url = lambda uid: r'http://olympiads.ru/cgi-bin/users?contest_id=25&user_id=%d&locale_id=1' % uid

download = lambda href: urllib.request.urlopen(href).read().decode()
downloadkoi8 = lambda href: urllib.request.urlopen(href).read().decode('koi8-r')

def get_infos(text):
  def get_user(userid):
    global USERS
    if userid not in USERS:
      try:
        src = download(user_url(userid))
        d = re.search(USER_STR, src).groupdict()
        d['grade'] = int(d['grade'])
        print('+++DOWNLOADED')
      except:
        d = {
          'name': 'undefined',
          'middlename': 'undefined',
          'surname': 'undefined',
          'status': 'undefined',
          'grade': 0,
        }
        print('++FAILED')
      USERS[userid] = d
    else:
      print('+++CACHED')
    return USERS[userid]
    
  def parse_problems(l):
    l = l[4:-5].split('</td><td>')
    d = {}
    for cur in range(len(l)):
      cl = l[cur]
      prob = chr(ord('A') + cur)
      d[prob] = {}
      try:
        d[prob] = re.match(r'(?P<score>.+?) \((?P<attempts>\d+?)\)', cl).groupdict()
        if d[prob]['score'].startswith('<b>'):
          d[prob]['score'] = d[prob]['score'][3:-4]
          d[prob]['solved'] = True
        else:
          d[prob]['solved'] = False
      except Exception as E:
        d[prob] = {'score': '0', 'attempts': '0', 'solved': False}
      for param in 'score', 'attempts':
        d[prob][param] = int(d[prob][param])
    return d
  for ma in re.finditer(RESULT_STR, text):
    d = ma.groupdict()
    for param in 'userid', 'grade':
      d[param] = int(d[param])
    d['results'] = parse_problems(d['results'])
    for param, val in get_user(d['userid']).items():
      d[param] = val
    print('--user-- %s' % d['login'])
    yield d

USERS = {}

def get_all_results():
  global USERS
  try:
    with open('users.pcl', 'rb') as uh:
      USERS = pickle.load(uh)
  except:
    pass
  try:
    page = 0
    while True:
      page += 1
      print('==Parsing page %d==' % page)
      for res in get_infos(downloadkoi8(page_url(page))):
        yield res
  except Exception as E:
    pass
    
  with open('users.pcl', 'wb') as uh:
    pickle.dump(USERS, uh, pickle.HIGHEST_PROTOCOL)

RESULTS = list(get_all_results())
with open('results.pcl', 'wb') as uh:
  pickle.dump(RESULTS, uh, pickle.HIGHEST_PROTOCOL)
  pickle.dump(datetime.datetime.today().strftime('%H:%M %d-%m-%y'), uh, pickle.HIGHEST_PROTOCOL)
